package net.yyge.apksigner.utils;

public class Base64 {
    // 私有构造函数，防止实例化（因为是 object）
    private Base64() {}

    // 静态实例，实现单例模式（对应 Kotlin object）
    private static final Base64 INSTANCE = new Base64();

    /**
     * 编码字节数组为 Base64 字符串
     */
    public static String encode(byte[] raw) {
        StringBuilder encoded = new StringBuilder();
        int i = 0;
        while (i < raw.length) {
            char[] block = encodeBlock(raw, i);
            for (char c : block) {
                encoded.append(c);
            }
            i += 3;
        }
        return encoded.toString();
    }

    /**
     * 解码 Base64 字符串为字节数组
     */
    public static byte[] decode(String base64) {
        int pad = 0;
        int i = base64.length() - 1;
        while (base64.charAt(i) == '=') {
            pad++;
            i--;
        }
        int length = base64.length() * 6 / 8 - pad;
        byte[] raw = new byte[length];
        int rawIndex = 0;
        i = 0;
        while (i < base64.length()) {
            int block = ((getValue(base64.charAt(i)) << 18)
                    + (getValue(base64.charAt(i + 1)) << 12)
                    + (getValue(base64.charAt(i + 2)) << 6)
                    + getValue(base64.charAt(i + 3)));
            int j = 0;
            while (j < 3 && rawIndex + j < raw.length) {
                raw[rawIndex + j] = (byte) ((block >> (8 * (2 - j))) & 0xff);
                j++;
            }
            rawIndex += 3;
            i += 4;
        }
        return raw;
    }

    /**
     * 编码三个字节为四个 Base64 字符（处理偏移量）
     */
    private static char[] encodeBlock(byte[] raw, int offset) {
        int block = 0;
        int slack = raw.length - offset - 1;
        int end = slack >= 2 ? 2 : slack;
        for (int idx = 0; idx <= end; idx++) {
            byte b = raw[offset + idx];
            int neuter = b < 0 ? b + 256 : b & 0xFF; // 等效于无符号转换
            block += neuter << (8 * (2 - idx));
        }
        char[] base64 = new char[4];
        for (int idx = 0; idx <= 3; idx++) {
            int sixBit = (block >>> (6 * (3 - idx))) & 0x3f;
            base64[idx] = getChar(sixBit);
        }
        if (slack < 1) {
            base64[2] = '=';
        }
        if (slack < 2) {
            base64[3] = '=';
        }
        return base64;
    }

    /**
     * 将 6-bit 值映射为 Base64 字符
     */
    private static char getChar(int sixBit) {
        if (sixBit >= 0 && sixBit <= 25) {
            return (char) ('A' + sixBit);
        }
        if (sixBit >= 26 && sixBit <= 51) {
            return (char) ('a' + (sixBit - 26));
        }
        if (sixBit >= 52 && sixBit <= 61) {
            return (char) ('0' + (sixBit - 52));
        }
        if (sixBit == 62) {
            return '+';
        }
        return sixBit == 63 ? '/' : '?';
    }

    /**
     * 将 Base64 字符映射为 6-bit 值
     */
    private static int getValue(char c) {
        if (c >= 'A' && c <= 'Z') {
            return c - 'A';
        }
        if (c >= 'a' && c <= 'z') {
            return c - 'a' + 26;
        }
        if (c >= '0' && c <= '9') {
            return c - '0' + 52;
        }
        if (c == '+') {
            return 62;
        }
        if (c == '/') {
            return 63;
        }
        return c == '=' ? 0 : -1;
    }
}